#include "client.h"
#include <iostream>

//打印信息
void Client::Print_info()
{
    if (!Dl_flg)
    {
        cout << "-----------------------------------" << endl;
        cout << "         网上购票预约系统             " << endl;
        cout << endl;
        cout << "     用户：游客     状态：未登录       " << endl;
        cout << "1 登陆        2 注册        3 退出   " << endl;
        cout << "-----------------------------------" << endl;
        cout << "请输入要操作的编号：" << endl;
        cin >> User_op;
        if (User_op == 3)
        {
            User_op = TC;
        }
    }
    else
    {
        cout << "-----------------------------------" << endl;
        cout << "   用户：" << user_name << "   状态：已登录" << endl;
        cout << "1 查看预约信息         2 预订    " << endl;
        cout << "3 查看我的预订         4 取消预订 " << endl;
        cout << "5 退出系统" << endl;
        cout << "-----------------------------------" << endl;

        cout << "请输入要操作的编号：" << endl;
        cin >> User_op;
        User_op += 2;
        if (User_op == 7)
        {
            User_op = TC;
        }
    }
}

// 注册
void Client::ZC_User() 
{
    cout << "输入手机号码:" << endl;
    cin >> user_tel;
    cout << "输入用户名:" << endl;
    cin >> user_name;
    cout << "输入密码:" << endl;

    string user_passwd;
    cin >> user_passwd;

    if (user_tel.empty() || user_passwd.empty() || user_name.empty())
    {
        cout << "输入不能有空" << endl;
        return;
    }

    Json::Value val;
    val["type"] = ZC;
    val["user_tel"] = user_tel;
    val["user_name"] = user_name;
    val["user_passwd"] = user_passwd;

    // 发送的注册报文
    send(sockfd, val.toStyledString().c_str(), strlen(val.toStyledString().c_str()), 0);
    // 接收状态信息
    char buff[128] = {0};
    if (recv(sockfd, buff, 127, 0) <= 0)
    {
        cout << "ser close or error" << endl;
        return;
    }

    Json::Value res_val;
    Json::Reader Read;
    Read.parse(buff, res_val);
    string status_str = res_val["status"].asString();

    if (status_str.compare("OK") != 0)
    {
        cout << "注册失败" << endl;
        return;
    }

    cout << "注册成功" << endl;
    Dl_flg = true;
}

// 登陆
void Client::DL_User() 
{
    cout << "输入手机号:" << endl;
    // string user_tel;
    cin >> user_tel;
    cout << "输入密码:" << endl;
    string user_passwd;
    cin >> user_passwd;

    if (user_tel.empty() || user_passwd.empty())
    {
        cout << "输入不能有空" << endl;
        return;
    }

    Json::Value val;
    val["type"] = DL;
    val["user_tel"] = user_tel;
    val["user_passwd"] = user_passwd;

    send(sockfd, val.toStyledString().c_str(), strlen(val.toStyledString().c_str()), 0);
    val.clear();
    char buff[128];
    if (recv(sockfd, buff, 127, 0) <= 0)
    {
        cout << "server close" << endl;
        return;
    }
    //成功收到数据 进行反序列化
    Json::Reader Read;
    if (!Read.parse(buff, val))
    {
        cout << "json err" << endl;
        return;
    }
    string status_str = val["status"].asString();
    if (status_str.compare("OK") != 0)
    {
        cout << "登陆失败" << endl;
        return;
    }

    user_name = val["user_name"].asString();
    cout << "登陆成功" << endl;
    Dl_flg = true;
}

//查看可预约的门票
void Client::CK_Ticket()
{
    Json::Value val;
    val["type"] = CK;
    send(sockfd, val.toStyledString().c_str(), strlen(val.toStyledString().c_str()), 0);
    // 接受可预约的信息并打印
    char buff[1024] = {0};
    int num = recv(sockfd, buff, 1023, 0);
    // cout<<buff<<endl;
    val.clear();
    Json::Reader Read;
    if (!Read.parse(buff, val))
    {
        cout << "Json err" << endl;
        return;
    }
    string status_str = val["status"].asString();
    if (status_str.compare("OK") != 0)
    {
        cout << "查看失败" << endl;
        return;
    }

    int Num = val["num"].asInt();
    if (Num == 0)
    {
        cout << "没有预约信息" << endl;
        return;
    }
    m_map.clear();
    cout << "-----------------------------------------------------" << endl;
    cout << "序号    地点名称    总票数    已预约票数    时间" << endl;
    for (int i = 0; i < Num; i++)
    {
        m_map.insert(make_pair(i, val["tk_arr"][i]["tk_id"].asString()));
        cout << i << "      ";
        cout << val["tk_arr"][i]["tk_name"].asString() << "    ";
        cout << val["tk_arr"][i]["tk_max"].asString() << "        ";
        cout << val["tk_arr"][i]["tk_num"].asString() << "         ";
        cout << val["tk_arr"][i]["tk_day"].asString() << "    " << endl;
    }
    cout << "-----------------------------------------------------" << endl;
}

//预约
void Client::YD_Ticket()
{
    CK_Ticket();
    int index = 0;
    cout << "请输入要预订的序号:" << endl;
    cin >> index;

    map<int, string>::iterator p = m_map.find(index);
    if (p == m_map.end())
    {
        cout << "输入无效" << endl;
        return;
    }

    Json::Value val;
    val["type"] = YD;
    val["user_tel"] = user_tel;
    val["tk_id"] = p->second;
    send(sockfd, val.toStyledString().c_str(), strlen(val.toStyledString().c_str()), 0);

    char buff[128] = {0};
    int n = recv(sockfd, buff, 127, 0);
    if (n <= 0)
    {
        cout << "ser close" << endl;
        return;
    }

    val.clear();
    Json::Reader Read;
    if (!Read.parse(buff, val))
    {
        cout << "Json error" << endl;
        return;
    }

    string status = val["status"].asString();
    if (status.compare("OK") != 0)
    {
        cout << "预订失败" << endl;
        return;
    }

    cout << "预订成功" << endl;
    return;
}

//查看自己的预约
void Client::CK_YY()
{
    Json::Value val;
    val["type"] = CKYY;
    val["user_tel"] = user_tel;
    send(sockfd, val.toStyledString().c_str(), strlen(val.toStyledString().c_str()), 0);

    char buff[1024] = {0};
    int num = recv(sockfd, buff, 1023, 0);
    // cout<<buff<<endl;
    val.clear();
    Json::Reader Read;
    if (!Read.parse(buff, val))
    {
        cout << "Json err" << endl;
        return;
    }
    
    string status_str = val["status"].asString();
    if( status_str.compare("OK") != 0 )
    {
        cout<<"查看失败"<<endl;
        return ;
    }
    int Num = val["num"].asInt();
    if( Num == 0 )
    {
        cout<<"没有预约信息"<<endl;
        return ;
    }
    yd_map.clear();
    cout << "----------------------------------" << endl;
    cout << "序号      地点名称      时间" << endl;
    for(int i=0; i<Num; i++)
    {
        yd_map.insert(make_pair(i,val["tk_arr"][i]["yd_id"].asString()));
        cout << i << "       ";
        cout << val["tk_arr"][i]["tk_name"].asString() <<"    ";
        cout << val["tk_arr"][i]["tk_datetime"].asString() <<"    " << endl;
    }
    cout << "----------------------------------" << endl;
}

//取消自己的预约
void Client::QX_YY()
{
    CK_YY();
    int index;
    cout<<"输入要取消的序号"<<endl;
    cin>>index;

    map<int, string>::iterator p = yd_map.find(index);
    if (p == yd_map.end())
    {
        cout << "输入无效" << endl;
        return;
    }

    Json::Value val;
    val["type"] = QX;
    val["yd_id"] = p->second;
    send(sockfd, val.toStyledString().c_str(), strlen(val.toStyledString().c_str()), 0);

    char buff[128] = {0};
    int n = recv(sockfd, buff, 127, 0);
    if (n <= 0)
    {
        cout << "ser close" << endl;
        return;
    }

    val.clear();
    Json::Reader Read;
    if (!Read.parse(buff, val))
    {
        cout << "Json error" << endl;
        return;
    }

    string status = val["status"].asString();
    if (status.compare("OK") != 0)
    {
        cout << "取消失败" << endl;
        return;
    }

    cout << "取消成功" << endl;
    return;
}


// 连接服务器端
bool Client::Connect_toServer()
{
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd == -1)
    {
        return false;
    }

    struct sockaddr_in saddr;
    memset(&saddr, 0, sizeof(saddr));
    saddr.sin_family = AF_INET;
    saddr.sin_port = htons(m_port);
    saddr.sin_addr.s_addr = inet_addr(m_ips.c_str());

    int res = connect(sockfd, (struct sockaddr *)&saddr, sizeof(saddr));
    if (res == -1)
    {
        return false;
    }

    return true;
}


// 传输json格式
void Client::Run()
{
    while (true)
    {
        Print_info();
        if( User_op == TC )
        {
            break;
        }

        switch (User_op)
        {
        case ZC:
            ZC_User();
            break;
        case DL:
            DL_User();
            break;
        case CK:
            CK_Ticket();
            break;
        case YD:
            YD_Ticket();
            break;
        case CKYY:
            CK_YY();
            break;
        case QX:
            QX_YY();
            break;
        case TC:
            running = false;
            break;
        default:
            cout << "输入无效，重新选择" << endl;
            break;
        }
    }
}

int main()
{
    Client cli;

    if (!cli.Connect_toServer())
    {
        cout << "connect error" << endl;
        exit(1);
    }

    cli.Run();

    exit(0);
}